
#pragma once
#ifndef CLIB_SOCK_H
#define CLIB_SOCK_H

#include "clib_type.h"
#include "clib_queue.h"
#include "clib_ip.h"
#include "clib_eth.h"
#include "clib_epoll.h"
#include "clib_listen.h"
#include "clib_tcp_stream.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef enum clib_sock_type {
    socket_type_unknow,
    socket_type_sock_tcp,
    socket_type_sock_udp,
    socket_type_listen,
    socket_type_epoll
} sock_type_t;

typedef enum clib_sock_opts {
    socket_opts_block   = 0,
    socket_opts_unblock = 1,
    socket_opts_bind    = 2,
} clib_sock_opts_t;

typedef struct ipv6_four_tuple_s
{
    ipaddr_t  l_addr;
    ipaddr_t  r_addr;
    u16_t     l_port;
    u16_t     r_port;
    u32_t     procotol;
} ipv6_tuple_t;

typedef struct ipv4_tuple_s
{
    u32_t       l_addr;
    u32_t       r_addr;
    u16_t       l_port;
    u16_t       r_port;
    u32_t       procotol;
} ipv4_tuple_t;

typedef struct tuple_s
{
    ipv4_tuple_t ipv4_tuple;
    ipv6_tuple_t ipv6_tuple;
} tuple_t;

typedef struct clib_sock_s
{
    clib_queue_t list;                 /** 其他互斥链表插入点 **/
    clib_queue_t ack_list;
    clib_queue_t wack_list;
    clib_queue_t recv_list;
    clib_queue_t send_list;
    clib_queue_t ep_list;
    clib_queue_t timerto_list;
    clib_queue_t timewait_list;
    clib_queue_t timeout_list;          /** timeout list **/
    clib_queue_t tuple_list;
    i32_t        sock_id;               /** socket fd    **/
    sock_type_t  sock_type;             /**  **/
    i16_t        core_id;
    i16_t        if_out;
    i16_t        numa_id;              
    u08_t        ipv4;                  /** AF_INET6 AF_INET **/
    u08_t        protocol;  
    u64_t        cur_time;
    eth_addr_t   l_mac;
    eth_addr_t   r_mac;
    u16_t        ip_id;
    u32_t        opts;
    
    union
    {
        ipv4_tuple_t ipv4_tuple;
        ipv6_tuple_t ipv6_tuple;
    };

    union
    {
        tcp_stream_t tcp_stream;
        tcp_listen_t tcp_listen;
        clib_epoll_t      epoll;
    };

    clib_ep_event_t ev;
    clib_epoll_t   *ep;
    u32_t           event;

    union
    {
        u32_t client:1,
             on_ack_list:1,
             on_timeout_list:1, 
             on_acpt_list:1,
             on_conn_list:1,
             on_close_list:1,
             on_recv_list:1,
             on_send_list:1, 
			 saw_timestamp:1,	/* whether peer sends timestamp */
			 sack_permit:1,		/* whether peer permits SACK */
			 control_list_waiting:1, 
			 have_reset:1,
			 is_external:1,		/* the peer node is locate outside of lan */
			 wait_for_acks:1,	/* if true, the sender should wait for acks to catch up before sending again */
             on_ep_ring:1,      /**< 在 epoll **/
             on_sh_ring:1;

        u32_t list_flag;
    };
    
    // u32_t descriptor;
    // systime_t timeout;
    // u08_t ttl;                  ///<Time-to-live value for unicast datagrams
    // u08_t multicastTtl;         ///<Time-to-live value for multicast datagrams

    // u16_t smss;                 ///<Sender maximum segment size
    // u16_t rmss;                 ///<Receiver maximum segment size
    // u32_t iss;                  ///<Initial send sequence number
    // u32_t irs;                  ///<Initial receive sequence number
    // clib_queue_t rcv_list;
    // clib_queue_t snd_list;
    // u32_t sndUna;               ///<Data that have been sent but not yet acknowledged
    // u32_t snd_next;             ///<Sequence number of the next byte to be sent
    // u16_t snd_user;             ///<Amount of data buffered but not yet sent
    // u16_t snd_Wnd;              ///<Size of the send window
    // u16_t maxSndWnd;            ///<Maximum send window it has seen so far on the connection
    // u32_t sndWl1;               ///<Segment sequence number used for last window update
    // u32_t sndWl2;               ///<Segment acknowledgment number used for last window update

    // u32_t rcv_next;             ///<Receive next sequence number
    // u16_t rcv_user;             ///<Number of data received but not yet consumed
    // u16_t rcvWnd;               ///<Receive window

} clib_sock_t;

/**
 * @brief sock初始化
 * 
 * @param sock  sock结构
 * @param sfd   初始化socket id
 */
void
clib_sock_init(clib_sock_t* sock, i32_t sfd);

void
clib_sock_clean(clib_sock_t* sock);

i32_t
clib_sock_ipv4_init(clib_sock_t* sock, sock_type_t type, tuple_t *tuple);

i32_t
clib_sock_ipv6_init(clib_sock_t* sock, sock_type_t type, tuple_t *tuple);

#ifdef __cplusplus
}
#endif

#endif